import { history, Effect, Reducer } from 'umi';
import { message } from 'antd';
import { isEmpty, sortBy } from 'lodash';

import { getPageSize } from '@/utils/pdfUtils';
import { serverBmp } from '@/utils/utils';

import { invocations, queryBlueprintHistoryCompareInfo } from '../service';

interface CompareResultSet {
  information: {
    miss: number[];
    increas: number[];
  };
  page_bbox: {
    relation: [number, number];
    m_bbox: [string[]];
    o_bbox: [string[]];
  }[];
}

export interface ConnectState {
  compare: StateType;
}

export interface StateType {
  compareList: any[];
  compareMarks: [any[], any[]];
  modify: any;
  original: any;
  treeData: any[];
}

export interface ModelType {
  namespace: string;
  state: StateType;
  effects: {
    fetch: Effect;
    pdfCompare: Effect;
  };
  reducers: {
    save: Reducer<StateType>;
  };
}

const transMark = (page: number, sourceData: [], { width = 0, height = 0 }) => {
  return sourceData.map((mark: any) => {
    const x = mark[0];
    const y = mark[1];
    const w = mark[2];
    const h = mark[3];
    return {
      page,
      type: 'rect',
      data: {
        x: x * width,
        y: y * height,
        width: w * width,
        height: h * height,
      },
    };
  });
};

const createTreeData = (datasource: CompareResultSet) => {
  const {
    information, // 多页少页数据
    page_bbox: pageBbox, // 每页对比结果
  } = datasource;
  const treeData = [];
  const { miss, increas } = information;
  treeData.push({
    key: '1',
    title: '单页差异',
    selectable: false,
    children: sortBy(
      pageBbox.filter((item) => {
        const { m_bbox: mBbox, o_bbox: oBbox } = item;
        return !(isEmpty(mBbox) && isEmpty(oBbox));
      }),
      (item) => {
        const { relation } = item;
        return relation[0];
      },
    ).map((item, i) => {
      const { relation, m_bbox: mBbox, o_bbox: oBbox } = item;
      const mPage = relation[0] + 1;
      const oPage = relation[1] + 1;
      return {
        key: `1-${i}`,
        title: `[左${oPage}, 右${mPage}]页`,
        selectable: true,
        type: 'diff',
        data: {
          mPage,
          oPage,
          mMarks: mBbox,
          oMarks: oBbox,
        },
      };
    }),
  });
  treeData.push({
    key: '0',
    title: '缺页多页统计',
    selectable: false,
    children: [
      {
        key: '0-1',
        title: '缺页',
        selectable: false,
        children: miss.map((i) => ({
          key: `0-1-${i}`,
          title: `第${i + 1}页`,
          selectable: true,
          type: 'miss',
          data: {
            page: i + 1,
          },
        })),
      },
      {
        key: '0-2',
        title: '多页',
        selectable: false,
        children: increas.map((i) => ({
          key: `0-2-${i}`,
          title: `第${i + 1}页`,
          selectable: true,
          type: 'increas',
          data: {
            page: i + 1,
          },
        })),
      },
    ],
  });
  return treeData;
};

const Model: ModelType = {
  namespace: 'compare',

  state: {
    modify: {},
    original: {},
    compareList: [],
    compareMarks: [[], []],
    treeData: [],
  },

  effects: {
    *fetch({ payload }, { call, put }) {
      const response = yield call(queryBlueprintHistoryCompareInfo, payload);
      if (response && response.code === 0) {
        const { modify, original } = response.data;
        const compareList = [];
        modify.url = `${serverBmp}${modify.url}`;
        original.url = `${serverBmp}${original.url}`;
        compareList.push(modify);
        compareList.push(original);
        yield put({
          type: 'save',
          payload: {
            modify,
            original,
            compareList,
          },
        });
        yield put({
          type: 'pdfCompare',
          payload: {
            compareList,
          },
          callback: (success: boolean, msg: string) => {
            if (!success) {
              message.error(msg);
            }
          },
        });
      } else {
        history.push('/404');
      }
    },
    *pdfCompare({ payload, callback }, { select, call, put }) {
      const { compareList } = payload;
      if (compareList && Array.isArray(compareList) && compareList.length === 2) {
        const [m, o] = compareList;
        const response = yield call(invocations, { m: m.url, o: o.url });
        if (response) {
          if (Array.isArray(response)) {
            const {
              // information,
              page_bbox: pageBbox,
            } = response[0];
            // const { miss, increas } = information;
            const compareMarks = yield select((state: ConnectState) => state.compare.compareMarks);
            for (let i = 0; i < pageBbox.length; i += 1) {
              const { relation, m_bbox: mBbox, o_bbox: oBbox } = pageBbox[i];
              const mPage: number = relation[0];
              const mSize = yield getPageSize({ url: compareList[0].url, page: mPage + 1 });
              compareMarks[0] = compareMarks[0].concat(
                transMark(mPage + 1, mBbox, { width: mSize.width, height: mSize.height }),
              );
              const oPage: number = relation[1];
              const oSize = yield getPageSize({ url: compareList[1].url, page: oPage + 1 });
              compareMarks[1] = compareMarks[1].concat(
                transMark(oPage + 1, oBbox, { width: oSize.width, height: oSize.height }),
              );
            }
            const treeData = createTreeData(response[0]);
            yield put({
              type: 'save',
              payload: {
                compareMarks,
                treeData,
              },
            });
            if (callback) callback(true);
          } else {
            const { error_code: errorCode } = response;
            if (errorCode) {
              yield put({
                type: 'save',
                payload: {
                  compareMarks: [],
                },
              });
              // eslint-disable-next-line no-console
              console.log(response);
              callback(false, `比对失败！`);
            }
          }
        } else if (callback) {
          yield put({
            type: 'save',
            payload: {
              compareMarks: [],
            },
          });
          callback(false, '比对失败！');
        }
      }
    },
  },

  reducers: {
    save(state, { payload }) {
      return {
        ...state,
        ...payload,
      };
    },
  },
};

export default Model;
